# coding:utf-8
"""
Author: 11203
Date:  16:15
Name: user_resources
user资源类
"""
import random

from flask import render_template, current_app, request  # 当前app应用上下文环境
from flask_limiter.util import get_remote_address
from flask_restful import Resource, reqparse
from flask_restful.reqparse import RequestParser
from sqlalchemy import or_
from werkzeug.security import check_password_hash

from common.models import db
from common.models.user import User
from common.others.request_decorators import login_required
from common.utils import redis_utils, token_utils
from common.utils.limiter_utils import limiter
from common.utils.regexp_utils import regexp_mobile, regexp, regexp_email
from common.utils.send_utils import email_send
from shopping.resources.user import contants

class TestRequest(Resource):
    """
    测试restful方法拦截器
    """
    method_decorators = {
        'post': [login_required]
    }
    def post(self):
        return {'hello': '测试'}


class UserResource(Resource):
    """
    用户资源类，用于用户的相关请求
    """

    ERROR_MESSAGE = '发送次数过多'

    # limiter.limit(限流的速率, 限制条件, 返回的错误信息)
    decorators = [limiter.limit(contants.LIMIT_CODE_BY,
                                key_func=lambda: request.args.get('vnumber'),
                                error_message=ERROR_MESSAGE),
                  limiter.limit(contants.LIMIT_CODE_BY_REMOTE_ADDR,
                                key_func=get_remote_address,
                                error_message=ERROR_MESSAGE)
                  ]

    # 发送邮箱验证码（后续更改为手机号验证码）
    def get(self) -> dict:
        vnumber = request.args.get('vnumber')
        # 生成随机验证码（5位）
        v_code = random.randint(00000, 99999)

        # 读取模板并返回渲染界面
        e_str = render_template('email_render.html', v_code=v_code)
        res = email_send(e_str, vnumber, '邮件验证码【****】')
        res['vnumber'] = vnumber

        # 验证码存入redis中，用于客户端验证（验证码时效为5分钟）
        # param1: key | param2: 过期时间 | param3: 值（这里是验证码）
        redis_utils.redis_client.setex('shopping:code:{vnumber}'.format(vnumber=vnumber),
                                       contants.REDIS_DATA_EXPIRES,
                                       v_code)

        return res


class AuthorizationResource(Resource):
    """
    提交邮箱号或手机号与验证码进行验证
    :param vnumber 邮箱号或手机号
    :param code    验证码
    """

    def post(self):
        # 先对提交的参数进行数据合法性验证
        rp = reqparse.RequestParser()
        rp.add_argument('vnumber', type=regexp_email, required=True)
        rp.add_argument('code', type=regexp(r'^\d{5}$'), required=True)

        args = rp.parse_args()
        vnumber = args['vnumber']
        code = args['code']

        # 获得redis保存中的验证码
        r_key = 'shopping:code:{vnumber}'.format(vnumber=vnumber)
        try:
            real_code = redis_utils.redis_client.get(r_key)
        except ConnectionError as ce:
            current_app.logger.error(ce)
            # 请求结果, 响应码
            return {'message': 'redis 链接异常'}, 400

        # 如果验证码非法（没有获取到或者验证码不相等）
        if not real_code or real_code.decode() != code:
            return {'message': '验证码错误'}, 400
        # 不返回响应码，默认为200
        return {'message': '校验成功', 'vnumber': vnumber}


class RegisterUserResource(Resource):
    """
    填写账号信息，完成用户的注册
    """

    def post(self):
        rp = RequestParser()
        rp.add_argument('vnumber', type=regexp_email, required=True)  # 这里是邮箱号
        rp.add_argument('phone', type=regexp_mobile, required=True)
        rp.add_argument('username', type=str, required=True)
        rp.add_argument('password', type=str, required=True)

        args = rp.parse_args()
        password = args.password
        username = args.username
        phone = args.phone
        vnumber = args.vnumber

        # 验证用户名是否唯一，先从数据库中根据当前用户名查询是否存在
        u = User.query.filter(or_(User.username == username, User.email == vnumber, User.phone == phone)).first()
        if u:  # 用户名已经存在
            current_app.logger.info('{username}: 用户名已经存在'.format(username=username))
            return {'message': '当前账户已存在'}, 400

        # 未查到用户信息，则可以新增账户
        u = User(username=username, pwd=password, email=vnumber, phone=phone, status=0, is_delete=0)
        db.session.add(u)
        db.session.commit()
        return {'message': '保存成功'}


class LoginUserResource(Resource):
    """
    账户登录
    """

    def post(self):
        rp = RequestParser()
        # 验证账户名
        rp.add_argument('username', type=str, required=True)
        rp.add_argument('password', type=str, required=True)

        args = rp.parse_args()
        username = args.username
        password = args.password

        # 验证账户并登录（Token设置）
        account_user = User.query.filter(User.username == username).first()

        if account_user:
            if account_user.check_pwd(password):

                # 验证成功后发放token令牌
                token = token_utils.create_token_by_pyjwt(account_user.id)
                return {'message': '登录成功', 'token': token}

        return {'message': '账户或密码错误'}, 400
